/**
* AutoSWF - Cody Cushing. March 26, 2009
* Copyright (c) 2009 Cody Cushing
* No use restrictions. Maintain this notice in all versions. 
**/

package com.autoswf.core
{
	import flash.errors.IllegalOperationError;
	
	import flexunit.framework.TestCase;

	public class ChainLinkTest extends TestCase
	{
		private var chainLink:ChainLink;
		private var mockLink1:MockChainLink;
		private var mockLink2:MockChainLink;

		public function ChainLinkTest(methodName:String=null)
		{
			super(methodName);
		}
		
		override public function setUp():void
		{
			mockLink1 = new MockChainLink("mockLink1");
			mockLink2 = new MockChainLink("mockLink2")
			chainLink = new ChainLink("testLink");
		}
		
		public function testGetId():void
		{
			assertEquals("cannot access id", "testLink", chainLink.id);
		}
		
		public function testToString():void
		{
			assertEquals("toString did not resolve to id", "testLink", String(chainLink));
		}
		
		public function testRemoveParentLink():void
		{
			chainLink.addParentLink(mockLink1);
			chainLink.removeParentLink(mockLink1);
			chainLink.sendUpChain("message");
			assertNull("message resolved to removed parent", mockLink1.sendUpChainResult);
		}
		
		public function testAddChildIdCollision():void
		{
			var mockLink1:MockChainLink = new MockChainLink("mockLink");
			var mockLink2:MockChainLink = new MockChainLink("mockLink");
			chainLink.addChildLink(mockLink1);
			
			var flag:Boolean = false;
			try
			{
				chainLink.addChildLink(mockLink2);
			}
			catch(error:IllegalOperationError)
			{
				flag = true;
			}
			assertTrue("child id collision did not throw error", flag);
		}
		
		public function testRemoveChildLink():void
		{
			chainLink.addChildLink(mockLink1);
			chainLink.removeChildLink(mockLink1);
			chainLink.sendDownChain("mockLink1->message");
			assertNull("message resolved to removed child", mockLink1.sendDownChainResult);
		}
		
		public function testSendUpChain():void
		{
			chainLink.addParentLink(mockLink1);
			
			chainLink.sendUpChain("message");
			assertEquals("child did not prepend its id", "testLink->message", mockLink1.sendUpChainResult);			
		}
		
		public function testSendDownChain():void
		{
			chainLink.addChildLink(mockLink1);
			chainLink.addChildLink(mockLink2);
			
			chainLink.sendDownChain("message");
			assertNull("no valid id, but request resolved to child", mockLink1.sendDownChainResult);

			chainLink.sendDownChain("mockLink1->message1");
			assertEquals("correct id, but message was not passed", "message1", mockLink1.sendDownChainResult);
			assertNull("message resolved to wrong child", mockLink2.sendDownChainResult);			
		}
		
		/**  test sendDownChain	ability to access member properties via reflection	 */		
		public function testAccessProperty():void
		{
			assertEquals("unable to access public property", "testLink", chainLink.sendDownChain("id"));
			
			assertNull("access private property", chainLink.sendDownChain("_id"));
		}
		
		public function testAccessPropertyOnClient():void
		{
			var testClient:Object = {};
			testClient.prop = "value";
			chainLink.client = testClient;
			
			assertEquals("failed to retrieve property on client object", "value", chainLink.sendDownChain("prop"));
		}
		
		public function testInvokeFunctionOnClient():void
		{
			var flag:Boolean = false;
			var testClient:Object = {};
			testClient.func = function():void
			{
				flag = true;
			}
			chainLink.client = testClient;
			chainLink.sendDownChain(new Transport("func"));
			assertTrue("failed to invoke function on client", flag);
		}
		
		public function testAccessPropertyOnSubclass():void
		{
			var subclass:ChainLinkSubclass = new ChainLinkSubclass("subclassId");
			assertEquals("failed to retrieve property on subclass", "testVal", subclass.sendDownChain("testProperty"));
		}
		
		public function testAccessFunctionOnSubclass():void
		{
			var subclass:ChainLinkSubclass = new ChainLinkSubclass("subclassId");
			assertEquals("failed to retrieve property on subclass", "functionResult", subclass.sendDownChain("testFunction"));
		}
		
	}
}
